package com.example.xpvideo.config;

import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.example.xpvideo.entity.ResponseResult;
import com.example.xpvideo.enums.ErrCodeEnum;
import com.example.xpvideo.exception.ErrorException;
import org.springframework.http.HttpStatus;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * The type Global exception handler.
 *
 * @ClassName: GlobalExceptionHandler
 * @Description: GlobalExceptionHandler
 * @Author: zzz
 * @Date: 2020 -04-04 21:45
 */
@ControllerAdvice
@ResponseBody
public class GlobalExceptionHandler {

    /**
     * Handle method argument not valid exception response result.
     *
     * @param e the e
     * @return the response result
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseResult<Object> handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
        return getObjectResponseResult(e.getBindingResult(), e);
    }

    /**
     * Handle bind exception response result.
     *
     * @param e the e
     * @return the response result
     */
    @ExceptionHandler(BindException.class)
    public ResponseResult<Object> handleBindException(BindException e) {
        return getObjectResponseResult(e.getBindingResult(), e);
    }

    /**
     * Handle bind exception response result.
     *
     * @param e the e
     * @return the response result
     */
    @ExceptionHandler(ConstraintViolationException.class)
    public ResponseResult<Object> handleBindException(ConstraintViolationException e) {
        Set<ConstraintViolation<?>> constraintViolations = e.getConstraintViolations();
        Map<String, String> errorMap = new HashMap<>(16);
        constraintViolations.forEach((fieldError) -> {
            String toString = fieldError.getPropertyPath()
                    .toString();
            String[] split = toString.split("\\.");
            int length = split.length;
            if (length>0){
                errorMap.put(split[length-1], fieldError.getMessage());
            }else {
                errorMap.put(toString, fieldError.getMessage());
            }
        });
        return  ResponseResult.responseResult(ErrCodeEnum.unknown_10001, errorMap);
    }

    private ResponseResult<Object> getObjectResponseResult(BindingResult bindingResult2,
                                                           Exception e) {
        BindingResult bindingResult = bindingResult2;
        Map<String, String> errorMap = new HashMap<>(16);
        bindingResult.getFieldErrors()
                .forEach((fieldError) -> {
                            errorMap.put(fieldError.getField(), fieldError.getDefaultMessage());
                }
                );
        return ResponseResult.responseResult(ErrCodeEnum.unknown_10001, errorMap);
    }


    /**
     * All exception handler response result.
     *
     * @param request  the request
     * @param response the response
     * @param e        the e
     * @return the response result
     */
    @ExceptionHandler(value = Exception.class)
    public ResponseResult<Object> allExceptionHandler(HttpServletRequest request,
                                                      HttpServletResponse response,
                                                      Exception e) {

        e.printStackTrace();
        // 可以在日志中输出完整的错误a信息，""里要写内容,不能在此处去打错误锚点（不能使用log.error("test fail-{},{}",a,e)）无法打出全部日志
        // response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
        return ResponseResult.responseResult(HttpStatus.INTERNAL_SERVER_ERROR.value(), e.getMessage());

    }


    /**
     * Handle error exception response result.
     *
     * @param e the e
     * @return the response result
     */
    @ExceptionHandler(ErrorException.class)
    public ResponseResult<Object> handleErrorException(ErrorException e) {
        Integer i = e.getCode();
        if (!ObjectUtils.isEmpty(e.getApiMessage())) {
            return ResponseResult.responseResult(i, e.getApiMessage());

        }
        return ResponseResult.responseResult(i, e.getMessage());
    }


}